﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Reflection
Imports System.Runtime.Serialization

Namespace System.Workflow.ComponentModel.Serialization
    Friend NotInheritable Class DictionarySurrogate
        Implements ISerializationSurrogate
        ' Methods
        Private Sub System.Runtime.Serialization.ISerializationSurrogate.GetObjectData(ByVal obj As Object, ByVal info As SerializationInfo, ByVal context As StreamingContext) Implements ISerializationSurrogate.GetObjectData
            If (Not obj.GetType.IsGenericType OrElse (Not obj.GetType.GetGenericTypeDefinition Is GetType(Dictionary([Of] ,)))) Then
                Throw New ArgumentException(SR.GetString("Error_InvalidArgumentValue"), "obj")
            End If
            Dim genericArguments As Type() = obj.GetType.GetGenericArguments
            If (genericArguments.Length <> 2) Then
                Throw New ArgumentException(SR.GetString("Error_InvalidArgumentValue"), "obj")
            End If
            Dim property As PropertyInfo = obj.GetType.GetProperty("Keys")
            If ([property] Is Nothing) Then
                Throw New NullReferenceException("keysProperty")
            End If
            Dim list As New ArrayList([TryCast]([property].GetValue(obj, Nothing),ICollection))
            Dim info3 As PropertyInfo = obj.GetType.GetProperty("Values")
            If (info3 Is Nothing) Then
                Throw New NullReferenceException("valuesProperty")
            End If
            Dim list2 As New ArrayList([TryCast](info3.GetValue(obj, Nothing),ICollection))
            If (list.Count = 1) Then
                info.AddValue("key", list.Item(0))
                info.AddValue("value", list2.Item(0))
            ElseIf (list.Count > 1) Then
                info.AddValue("keys", list.ToArray)
                info.AddValue("values", list2.ToArray)
            End If
            info.AddValue("keyType", genericArguments(0))
            info.AddValue("valueType", genericArguments(1))
            info.SetType(GetType(DictionaryRef))
        End Sub

        Private Function System.Runtime.Serialization.ISerializationSurrogate.SetObjectData(ByVal obj As Object, ByVal info As SerializationInfo, ByVal context As StreamingContext, ByVal selector As ISurrogateSelector) As Object Implements ISerializationSurrogate.SetObjectData
            Return Nothing
        End Function


        ' Nested Types
        <Serializable> _
        Private NotInheritable Class DictionaryRef
            Implements IObjectReference, IDeserializationCallback
            ' Methods
            Private Sub System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(ByVal sender As Object) Implements IDeserializationCallback.OnDeserialization
                If (Not Me.dictionary Is Nothing) Then
                    Dim method As MethodInfo = Me.dictionary.GetType.GetMethod("Add")
                    If (method Is Nothing) Then
                        Throw New NullReferenceException("addMethod")
                    End If
                    Dim parameters As Object() = New Object(2  - 1) {}
                    If (Not Me.keys Is Nothing) Then
                        Dim i As Integer
                        For i = 0 To Me.keys.Count - 1
                            parameters(0) = Me.keys.Item(i)
                            parameters(1) = Me.values.Item(i)
                            method.Invoke(Me.dictionary, parameters)
                        Next i
                    ElseIf (Not Me.key Is Nothing) Then
                        parameters(0) = Me.key
                        parameters(1) = Me.value
                        method.Invoke(Me.dictionary, parameters)
                    End If
                End If
                Me.dictionary = Nothing
            End Sub

            Private Function System.Runtime.Serialization.IObjectReference.GetRealObject(ByVal context As StreamingContext) As Object Implements IObjectReference.GetRealObject
                If (Me.dictionary Is Nothing) Then
                    Dim type As Type = GetType(Dictionary([Of] Integer, Integer)).GetGenericTypeDefinition.MakeGenericType(New Type() { Me.keyType, Me.valueType })
                    Me.dictionary = type.GetConstructor(Type.EmptyTypes).Invoke(Nothing)
                End If
                Return Me.dictionary
            End Function


            ' Fields
            <NonSerialized> _
            Private dictionary As Object
            <OptionalField> _
            Private key As Object
            <OptionalField> _
            Private keys As IList
            Private keyType As Type
            <OptionalField> _
            Private value As Object
            <OptionalField> _
            Private values As IList
            Private valueType As Type
        End Class
    End Class
End Namespace

